package com.fare.taluo.core.domain.crawl.adapter.sub;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;

import net.htmlparser.jericho.Element;
import net.htmlparser.jericho.Source;

import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.cookie.Cookie;
import org.apache.http.impl.client.AbstractHttpClient;
import org.apache.http.util.EntityUtils;

import com.fare.taluo.conf.ConfigContainer;
import com.fare.taluo.core.domain.ChannelConst;
import com.fare.taluo.core.domain.crawl.CrawlTaskModel;
import com.fare.taluo.core.domain.crawl.PageErrorResultException;
import com.fare.taluo.core.domain.crawl.adapter.AbstractAdapter;
import com.fare.taluo.core.domain.crawl.adapter.CrawlAdapterFactory;
import com.fare.taluo.core.domain.entity.crawl.FreightPriceEntity;
import com.fare.taluo.util.DateUtils;

/**
 * 海航数据抓取接口实现
 * 
 * @date 2012-11-23<br>
 * @author TANJIALIN
 */
public class HaiNanAirHttpClientAdapter extends AbstractAdapter {
	private HttpClient client = null;
	private String cookeiStr;
	private String referer;

	public HaiNanAirHttpClientAdapter(CrawlTaskModel taskModel) {
		super(taskModel);
	}

	public List<Object> paraseToVo(Object fetchObject) {
		String tempResult = fetchObject.toString().trim();
		List<Object> list = parseSource(new Source(tempResult));
		tempResult = null;
		return list;
	}

	private List<Object> parseSource(Source source) {
		List<Object> dataList = new ArrayList<Object>();
		List<Element> elementList = source.getAllElementsByClass("view_table");
		for (Iterator<Element> iterator = elementList.iterator(); iterator
				.hasNext();) {
			Element element = (Element) iterator.next();
			List<Element> trLists = element.getAllElements("tr");
			for (int i = 0; i < trLists.size(); i++)
				if (i % 2 == 0) {
					String filghtId = getTableContent(element, i, 0)
							.getTextExtractor().toString();
					String filgType = getTableContent(element, i, 3)
							.getTextExtractor().toString();
					String dtime = getTableContent(element, i, 1)
							.getTextExtractor().toString().trim();
					String startAndEndTime[] = dtime.replaceAll("\\s+", "-")
							.split("-");
					String jg1 = getTableContent(element, i, 4)
							.getTextExtractor().toString();
					String jg2 = getTableContent(element, i, 5)
							.getTextExtractor().toString();
					String jg3 = getTableContent(element, i, 6)
							.getTextExtractor().toString();
					String jg4 = getTableContent(element, i, 7)
							.getTextExtractor().toString();
					if (jg1.length() > 15)
						jg1 = jg1.substring(0, jg1.indexOf(" "));
					if (jg2.length() > 15)
						jg2 = jg2.substring(0, jg2.indexOf(" "));
					if (jg3.length() > 15)
						jg3 = jg3.substring(0, jg3.indexOf(" "));
					if (jg4.length() > 15)
						jg4 = jg4.substring(0, jg4.indexOf(" "));
					double highPrice = 15000D;
					double price_1 = Double.parseDouble(jg1
							.replace("unchecked", "")
							.replace("￥", "")
							.replace(
									"-",
									(new StringBuilder(String
											.valueOf(highPrice))).toString()));
					double price_2 = Double.parseDouble(jg2
							.replace("unchecked", "")
							.replace("￥", "")
							.replace(
									"-",
									(new StringBuilder(String
											.valueOf(highPrice))).toString()));
					double price_3 = Double.parseDouble(jg3
							.replace("unchecked", "")
							.replace("￥", "")
							.replace(
									"-",
									(new StringBuilder(String
											.valueOf(highPrice))).toString()));
					double price_4 = Double.parseDouble(jg4
							.replace("unchecked", "")
							.replace("￥", "")
							.replace(
									"-",
									(new StringBuilder(String
											.valueOf(highPrice))).toString()));
					double priceArr[] = { price_1, price_2, price_3, price_4 };
					double price[] = SortArray(priceArr);
					double lowerPriceValue = 0.0D;
					double highPriceValue = 0.0D;
					if (price[0] != highPrice)
						lowerPriceValue = price[0];
					for (int j = price.length - 1; j >= 0; j--) {
						if (price[j] == highPrice)
							continue;
						highPriceValue = price[j];
						break;
					}

					if (StringUtils.isNotBlank(startAndEndTime[0]))
						startAndEndTime[0] = startAndEndTime[0].endsWith("+") ? startAndEndTime[0]
								.substring(0, startAndEndTime[0].length() - 1)
								: startAndEndTime[0];
					if (StringUtils.isNotBlank(startAndEndTime[1]))
						startAndEndTime[1] = startAndEndTime[1].endsWith("+") ? startAndEndTime[1]
								.substring(0, startAndEndTime[1].length() - 1)
								: startAndEndTime[1];
					dataList.add(CrawlAdapterFactory.createPlaneInfo(taskModel,
							"HU", "海航", "海南航空股份有限公司", startAndEndTime[0],
							startAndEndTime[1], filghtId,
							String.valueOf(lowerPriceValue), null,
							String.valueOf(highPriceValue), filgType));
				}

		}

		return dataList;
	}

	public String getUrl() throws UnsupportedEncodingException {
		String url = "http://et.hnair.com/huet/bc10_av.do?";
		String tripType = "ONEWAY";
		SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
		String tdate = df.format(new Date());
		int dt = DateUtils.compare_date(taskModel.getFlightDate(), tdate);
		int dr = 0;
		String takeoffdate = taskModel.getFlightDate();
		String returndate = taskModel.getReturnFlightDate();
		if (dt < 0)
			takeoffdate = tdate;
		if (dr < 0)
			returndate = tdate;
		String params = (new StringBuilder(
				"preUrl=et.hnair.com&queryPassengerType=0&iscalendar=true&adultNum=1&bookSeatClass=E&type=on&childNum=0&dstCity="))
				.append(taskModel.getToCity())
				.append("&returnDate=")
				.append(returndate)
				.append("&")
				.append("tripType=")
				.append(tripType)
				.append("&takeoffDate=")
				.append(takeoffdate)
				.append("&")
				.append("sl_end2=")
				.append(URLEncoder.encode(taskModel.getToCityName(), "gb2312"))
				.append("&")
				.append("sl_start2=")
				.append(URLEncoder.encode(taskModel.getFromCityName(), "gb2312"))
				.append("&").append("orgCity=").append(taskModel.getFromCity())
				.toString();
		url = (new StringBuilder(String.valueOf(url))).append(params)
				.toString();
		// logger.info(url);
		return url;
	}

	private URI produceUri() throws URISyntaxException {
		return (new URIBuilder()).addParameter("preUrl", "et.hnair.com")
				.addParameter("queryPassengerType", "0")
				.addParameter("orgCity", taskModel.getFromCity())
				.addParameter("dstCity", taskModel.getToCity())
				.addParameter("sl_end2", taskModel.getToCityName())
				.addParameter("sl_start2", taskModel.getFromCityName())
				.addParameter("returnDate", taskModel.getReturnFlightDate())
				.addParameter("takeoffDate", taskModel.getFlightDate())
				.addParameter("iscalendar", "true")
				.addParameter("tripType", "ONEWAY")
				.addParameter("adultNum", "1")
				.addParameter("bookSeatClass", "E")
				.addParameter("childNum", "1").addParameter("type", "on")
				.setScheme("http").setHost("et.hnair.com")
				.setPath("/huet/bc10_av.do").build();
	}

	private URI produceWaittingUri() throws URISyntaxException {
		return (new URIBuilder()).addParameter("type", "on")
				.addParameter("doaction", "/huet/bc10_av.do")
				.addParameter("tripType", "ONEWAY")
				.addParameter("sl_start2", taskModel.getFromCityName())
				.addParameter("sl_end2", taskModel.getToCityName())
				.addParameter("orgCity", taskModel.getFromCity())
				.addParameter("dstCity", taskModel.getToCity())
				.addParameter("takeoffDate", taskModel.getFlightDate())
				.addParameter("returnDate", taskModel.getReturnFlightDate())
				.addParameter("bookSeatClass", "E")
				.addParameter("adultNum", "1").addParameter("childNum", "0")
				.addParameter("queryPassengerType", "0")
				.addParameter("iscalendar", "true").setScheme("http")
				.setHost("et.hnair.com").setPath("/huet/bc10waiting.do")
				.build();
	}

	public String getCookeiStr() {
		return cookeiStr;
	}

	public void setCookeiStr(String cookeiStr) {
		this.cookeiStr = cookeiStr;
	}

	public String getReferer() {
		return referer;
	}

	public void setReferer(String referer) {
		this.referer = referer;
	}

	private String fetchURI(URI uri) throws Exception {
		HttpPost request;
		HttpEntity entity;
		byte data[];
		request = null;
		HttpResponse response = null;
		entity = null;
		InputStream is = null;
		data = null;
		String s;
		try {
			if (client == null)
				client = super.getHttpClient();
			request = new HttpPost(uri);
			request.setHeader("Accept", "text/html, application/xhtml+xml, */*");
			request.setHeader("Accept-Encoding", "gzip, deflate");
			request.setHeader("Accept-Language", "zh-CN,en-US;q=0.5");
			request.setHeader("Connection", "keep-Alive");
			request.setHeader("Cache-Control", "no-cache");
			request.setHeader("Content-Type",
					"application/x-www-form-urlencoded");
			if (StringUtils.isNotBlank(cookeiStr))
				request.setHeader("Cookie", cookeiStr);
			request.setHeader("Host", "et.hnair.com");
			request.setHeader("User-Agent",
					"Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0");
			request.setHeader("Referer", referer);
			response = client.execute(request);
			entity = response.getEntity();
			if (entity != null) {
				is = entity.getContent();
				data = writeByte(is);
			}

			s = new String(data, "GBK");
		} finally {
			if (is != null)
				try {
					is.close();
				} catch (Exception e) {
				}
			;
			is = null;
			if (request != null)
				request.releaseConnection();
			if (entity != null)
				EntityUtils.consume(entity);
			entity = null;
			response = null;
			request = null;
		}
		return s;
	}

	protected byte[] writeByte(InputStream is) throws IOException {
		int count = 0;
		if (is == null)
			return new byte[0];
		ByteArrayOutputStream os = null;
		byte[] data = null;
		try {
			os = new ByteArrayOutputStream();
			data = new byte[1024];
			while ((count = is.read(data)) > 0)
				os.write(data, 0, count);

			return os.toByteArray();
		} finally {
			os = null;
			data = null;
		}
	}

	private void setRequestDatas() {
		AbstractHttpClient aclient = (AbstractHttpClient) client;
		List<Cookie> cookies = aclient.getCookieStore().getCookies();
		StringBuilder sbuilder = new StringBuilder();
		Cookie c;
		for (Iterator<Cookie> iterator = cookies.iterator(); iterator.hasNext(); sbuilder
				.append(c.getName()).append("=").append(c.getValue())
				.append(";"))
			c = (Cookie) iterator.next();

		cookeiStr = sbuilder.toString();
	}

	public Object fetch(String url) throws Exception {
		String s;
		try {
			setReferer("http://www.hnair.com/");
			fetchURI(produceWaittingUri());
			setRequestDatas();
			setReferer("http://et.hnair.com/huet/bc10waiting.do");
			s = fetchURI(produceUri());
			return s;
		} finally {
			referer = null;
			cookeiStr = null;
			client = null;
		}
	}

	public boolean validateFetch(Object fetchObject) throws Exception {
		if (fetchObject == null)
			return false;
		if (fetchObject instanceof String) {
			String result = com.fare.taluo.util.RegHtmlUtil.regStr((String) fetchObject,
					getErrors());
			if (result != null)
				throw new PageErrorResultException(result);
		}
		return true;
	}

	private List<String> getErrors() {
		List<String> errors = new ArrayList<String>();
		errors.add("404 Not Found");
		errors.add("HTTP.+404");
		errors.add("<title>系统错误提示信息</title>");
		errors.add("<h1>Error 501: Not Implemented</h1>");
		errors.add("<TITLE>ERROR: The requested URL could not be retrieved</TITLE>");
		errors.add("<TITLE>400 Bad Request</TITLE>");
		return errors;
	}

	public double[] SortArray(double x[]) {
		for (int i = 0; i < x.length; i++) {
			for (int j = i + 1; j < x.length; j++)
				if (x[i] > x[j]) {
					double temp = x[i];
					x[i] = x[j];
					x[j] = temp;
				}

		}

		return x;
	}

	public Element getTableContent(Element element, int rows, int cols) {
		Element resultElement = null;
		List<Element> trList = element.getAllElements("tr");
		if (rows < trList.size()) {
			Element trElement = (Element) trList.get(rows);
			List<Element> tdList = trElement.getAllElements("td");
			if (cols < tdList.size())
				resultElement = (Element) tdList.get(cols);
		}
		return resultElement;
	}

	public static void main(String arg[]) throws Exception {

		CrawlTaskModel taskModel = new CrawlTaskModel();
		taskModel.setGrabChannelId(ChannelConst.CHANNEL_HN);
		taskModel.setFromCity("CAN");
		taskModel.setFromCityName("广州");
		taskModel.setToCity("PEK");
		taskModel.setToCityName("北京");
		taskModel.setFlightDate("2013-06-08");
		try {
			//抓取数据相关配置
			ConfigContainer.getInstance().register("com.fare.taluo.core.domain.crawl.CrawlPropertiesLoader");
			HaiNanAirHttpClientAdapter c = new HaiNanAirHttpClientAdapter(taskModel);
			//String obj = FileUtils.readFileToString(new File(
			//		"f:/temp/hbase/hainan.html"));
			Object obj = c.fetch(null);
			List<Object> results = c.paraseToVo(obj);
			FreightPriceEntity p = null;
			for (Iterator<Object> iterator = results.iterator(); iterator.hasNext();) {
				Object o = iterator.next();
				p = (FreightPriceEntity) o;
				System.out.println(p.toString());
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			Runtime.getRuntime().exit(1);
		}
	}

}
